home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / progut~1 / proff.zoo / ltb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-04  |  6.5 KB  |  297 lines

  1. /*
  2.  * ltb.c - Lexical Table Builder
  3.  *
  4.  * Functional description:
  5.  *
  6.  *    This program builds a file containing the data
  7.  *    structures of a compile-time-initialised hash table. 
  8.  *    This hash table may later be used for lexical analysis,
  9.  *    where number of symbols to look up is sufficiently large
  10.  *    to avoid a run-time table initialization.
  11.  *    In order to guarantee the success of this setup, the 
  12.  *    hash routine, the lookup and install routines should be
  13.  *    the same between ltb and the lexical analysis.
  14.  *
  15.  * synopsis:
  16.  *
  17.  *    ltb <input file> [table name]
  18.  *
  19.  * input file format:
  20.  *
  21.  *    <token>  <value identifier> [flag value]
  22.  *
  23.  *    token:         string of alphanumeric characters to be 
  24.  *                   matched by the lexical analyser (no blanks).
  25.  *            these token strings are "installed" to a hash
  26.  *            table by ltb to avoid run-time overhead.
  27.  *    value 
  28.  *    identifier:    A constant name to be used internally by the
  29.  *            lexical analyser in place of the actual
  30.  *            token value. a "#define <indentifier> <value>"
  31.  *            is generated for each value identifier, where
  32.  *            value is an odd and unique integer constant. If
  33.  *            the value identifier is a `*' (star), then the
  34.  *            previous value is repeated. Thus:
  35.  *
  36.  *                   token   ident.   flag
  37.  *
  38.  *                sp    SP    1
  39.  *                space    *         { inherits SP  }
  40.  *                blank    *          { inherits SP  }
  41.  *                .    .    .
  42.  *                .    .    .
  43.  *
  44.  *    flag value:    An additional integer field to pass flags etc. to
  45.  *            the lexical analyser. If not specified, set to
  46.  *            0. token value field must be present for this field
  47.  *            to be obtained.
  48.  *
  49.  * outputs:
  50.  *
  51.  *    ltb generates two C include files:
  52.  *
  53.  *        [tablename].d:  compile time lexical constants (defines)
  54.  *        [tablename].h:    initialised hash table.
  55.  *
  56.  *    where [tablename] is the name of the hash table as specified
  57.  *    in the command line of ltb. If not specified, "lextab" is used
  58.  *    as a default.
  59.  *
  60.  * routines used by LTB:
  61.  *
  62.  *    hash, lookup and a modified version of install routines,
  63.  *    as defined in K&R, pp. 134 - 136.
  64.  *
  65.  * Application areas:
  66.  *
  67.  *    Lexical analysers for compilers, interpreters, spelling
  68.  *    checkers.
  69.  *
  70.  * Author:
  71.  *    Ozan S. Yigit
  72.  *    Dept. of Computer Science
  73.  *    York University
  74.  *
  75.  */
  76.  
  77. #define MAXLINE        80
  78. #define MAXSYM        80
  79.  
  80. #include <stdio.h>
  81. #include <ctype.h>
  82. #include "lookup.h"
  83.  
  84. struct
  85. lexlist    (*(*lextable))[];/* global pointer for lexical analyser hash table */
  86.  
  87. static struct lexlist *hashtab[HASHMAX];
  88. static struct lexlist *defitab[HASHMAX];
  89.  
  90. char *tabnam;        /* table name */
  91.  
  92. extern int hash();
  93. extern struct hashlist *lookup();
  94. extern struct hashlist *install();
  95. extern char *strsave();
  96. extern struct lexlist *lexinstal();
  97. extern struct lexlist *lexlook();
  98. extern struct lexlist *Remove();
  99. extern FILE *fopen(); /*   *fclose() */      /* won't compile otherwise */
  100.  
  101. main(argc,argv)
  102. int argc;
  103. char *argv[];
  104. {
  105.     FILE *fp;
  106.     char line[MAXLINE];
  107.     char sym[MAXSYM],def[MAXSYM];
  108.     register int val;
  109.     register int prev;
  110.     register char *p;
  111.     register char *ptr;
  112.     int flag;
  113.     struct lexlist *np, *lexlook();
  114.  
  115.     if (argc <= 2) {
  116.         fprintf(stderr,"%s [-<base>] <symbol file> [tablename]\r\n",
  117.         argv[0]);
  118.         exit(1);
  119.     }
  120.  
  121.     if (*argv[1] == '-') {
  122.         val = atoi(argv[1]+1);    /* skip "-" and convert */
  123.         val = (val & 1) ? val : val+1;
  124.         p = (char *)argv[2];
  125.     }
  126.     else {
  127.         val = 1;
  128.         p = (char *)argv[1];
  129.     }
  130.  
  131.     if (argc < 3)
  132.         tabnam = "lextab";
  133.     else
  134.         tabnam = argv[argc-1];
  135.  
  136.     if ((fp = fopen(p,"r")) == NULL) {
  137.         fprintf(stderr,"%s:cannot open.\r\n",argv[1]);
  138.         exit(1);
  139.     }
  140.     else {
  141.         prev = val;
  142.         while (fgets(line,MAXLINE,fp) != NULL) {
  143.             if (*line != '!') {
  144.                 flag = 0; 
  145.                 def[0] = '\0';
  146.                 ptr = line;
  147.                 while (isspace(*ptr))
  148.                     ptr++;
  149.                 if (*ptr == '\0')
  150.                     continue;
  151.                 sscanf(line,"%s %s %d",sym,def,&flag);
  152.                 if (!(def[0] == '*' && def[1] == '\0')) {
  153.                     if ((np = lexlook(def,defitab)) == NULL) {
  154.                         /* value define  */
  155.                         lexinstal(def,val,0,defitab);
  156.                         prev = val;
  157.                         val += 2;
  158.                     }
  159.                     else
  160.                         prev = np->val;
  161.                 }
  162.                  /* lexical token */
  163.                 lexinstal(sym,prev,flag,hashtab);
  164.             }
  165.         }
  166.         defgen();
  167.         lexgen();
  168.     }
  169. }
  170. /*
  171.  * lexgen - print out the hash table in static form
  172.  *
  173.  */
  174. lexgen()
  175. {
  176.     register int i;
  177.     register struct lexlist *np;
  178.     char filebuf[12];
  179.     char *file;
  180.     FILE *op;
  181.  
  182.     file = filebuf;
  183.  
  184.     strncpy(file,tabnam,8);
  185.     strcat(file,".h");
  186.  
  187.     if ((op = fopen(file,"w")) == NULL) {
  188.         fprintf(stderr,"%s: cannot create.\r\n",file);
  189.         exit(1);
  190.     }
  191.  
  192.     fprintf(op,"#ifndef STRUC_DEFINED\n\n");
  193.     fprintf(op,"\/\*\t%s\t\*\/\n\n%s\n%s\n%s\n%s\n%s\n",file,
  194.     "struct _lex_h {     char     *__s;",
  195.     "              int      __v;",
  196.     "              int       __f;",
  197.     "        struct  _lex_h  *__l;",
  198.     "};");
  199.     fprintf(op,"\n#define STRUC_DEFINED\n#endif\n");
  200.  
  201.     /*
  202.              * generate the hash table entries.
  203.              * each entry is followed by the next entry in its
  204.              * chain.
  205.              * In the operating systems with memory paging, this
  206.              * should have the extra advantage of localized
  207.              * memory referances.
  208.              *
  209.      */
  210.  
  211.     for (i=0; i < HASHMAX; i++)
  212.         if ((np = hashtab[i]) != NULL)
  213.             prnode(np,op);
  214.     /*
  215.              * At last, we generate the pointer array (hashtable).
  216.              * this table should be assigned to lextable global
  217.              * variable before using with lexlook() or lexinstal().
  218.              * lextable is defined in lookup.h
  219.              *
  220.      */
  221.  
  222.     fprintf(op,"\n\n\/\*  Hash Table \*\/\n\n");
  223.     fprintf(op,"struct _lex_h *%s[%d] = {\n\t",tabnam,HASHMAX);
  224.     for (i=0; i < HASHMAX - 1; i++) {
  225.         np = hashtab[i];
  226.         if(np == NULL)
  227.             fprintf(op,"NULL,\t");
  228.         else
  229.             fprintf(op,"\&__%s,\t", np->name);
  230.         if (i % 4 == 0)
  231.             fprintf(op,"\n\t");
  232.     }
  233.     np = hashtab[i];
  234.     if (np == NULL)
  235.         fprintf(op,"NULL  };\n");
  236.     else
  237.         fprintf(op,"\&__%s   };\n", np->name);
  238.  
  239.     fclose(op);
  240. }
  241.  
  242. /*
  243.  * prnode - print the current node. This routine is 
  244.  *        recursive such that printing starts from
  245.  *        the end of the given list
  246.  *
  247.  */
  248. prnode(np,op)
  249. register struct
  250. lexlist *np;
  251. FILE *op;
  252. {
  253.     if (np->link != NULL)
  254.         prnode(np->link,op);
  255.     fprintf(op,"struct\n_lex_h __%s = {  ",
  256.     np->name);
  257.     fprintf(op,"\"%s\",\n              %6d,%6d,",
  258.     np->name,
  259.     np->val,
  260.     np->flag);
  261.     if (np->link != NULL)
  262.         fprintf(op,"\&__%s };\n",
  263.         (np->link)->name);
  264.     else
  265.         fprintf(op,"NULL };\n");
  266. }    
  267.  
  268. /*
  269.  * defgen - generate a file containing the lexical
  270.  *        constants to be equated to lexical symbols
  271.  */
  272. defgen()
  273. {
  274.     register int i;
  275.     register struct lexlist *np;
  276.     char *file;
  277.     char filebuf[12];
  278.     FILE *op;
  279.  
  280.     file = filebuf;
  281.     strncpy(file,tabnam,8);
  282.     strcat(file,".d");
  283.  
  284.     if ((op = fopen(file,"w")) == NULL) {
  285.         fprintf(stderr,"%s: cannot create.\r\n",file);
  286.         exit(1);
  287.     }
  288.     for (i=0; i < HASHMAX; i++) {
  289.         for (np = defitab[i]; np != NULL; np = np->link)
  290.             fprintf(op,"\#define  %s\t%d\n",
  291.             np->name,
  292.             np->val);
  293.     }
  294.     fclose(op);
  295. }
  296.  
  297.